import os
import sys
import datetime

from PyQt5.QtWidgets import *
from PyQt5.QtSql import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *


def field_column(model):
    """ Создание словаря для QSqlQueryModel.
    Ключ - имя поля, значение - номер столбца."""
    D = {}
    for i in range(model.columnCount()):
        D[model.record().fieldName(i)] = i
    return D


class ModuleMenager(QDialog):
    """
    """
    def __init__(self, parent, rec_id):
        super().__init__(parent)
        self.rec_id = rec_id
        self.pict_empty = QPixmap('pict\\emptytrash.png')
        self.pict_full = QPixmap('pict\\fulltrash.png')
        self.create_ui()
        self.load_data(rec_id)

    def create_ui(self):

        #self.setStyleSheet("QLineEdit { background-color: yellow },"
        #                   "QGroupBox { background-color: red }")
        # self.edt_num_asu_new.setStyleSheet("background-color : red")

        # """ ЛЕВАЯ МАТРЕШКА."""

        """ЗАДАНИЕ"""

        vbox1 = QVBoxLayout()
        
        # форма 1
        form1 = QFormLayout()
        self.cmb_class = QComboBox()
        self.cmb_class.currentIndexChanged['QString'].connect(self.class_changed)
        form1.addRow("ЗАДАНИЕ", self.cmb_class)
        self.cmb_modification = QComboBox()
        self.lbl_modification = QLabel("ИЗМЕНИТЬ")
        form1.addRow(self.lbl_modification, self.cmb_modification)
        self.edt_num_asu_old = QLineEdit()
        self.lbl_num_asu_old = QLabel("СТАРЫЙ МАКЕТ")
        form1.addRow(self.lbl_num_asu_old, self.edt_num_asu_old)
        vbox1.addStretch(3)
        vbox1.addLayout(form1)
        vbox1.addStretch(5)
        
        # форма 2
        form2 = QFormLayout()
        self.cmb_city = QComboBox()
        form2.addRow("ГОРОД", self.cmb_city)
        self.edt_num_asu_new = QLineEdit()
        self.lbl_num_asu_new = QLabel("№ АСУ")
        form2.addRow(self.lbl_num_asu_new, self.edt_num_asu_new)
        self.edt_place = QLineEdit()
        self.lbl_place = QLabel("РУБРИКА")
        form2.addRow(self.lbl_place, self.edt_place)
        self.edt_num_out = QLineEdit()
        self.lbl_num_out = QLabel("НОМЕР")
        form2.addRow(self.lbl_num_out, self.edt_num_out)
        self.edt_proportions = QLineEdit()
        form2.addRow("ФОРМАТ", self.edt_proportions)
        gbox2 = QGroupBox()
        gbox2.setLayout(form2)

        vbox2 = QVBoxLayout()
        # форма 3
        form3 = QFormLayout()
        self.edt_color = QLineEdit()
        self.lbl_color = QLabel("ЦВЕТ")
        form3.addRow(self.lbl_color, self.edt_color)
        self.edt_picture = QLineEdit()
        self.lbl_picture = QLabel("КАРТИНКА")
        form3.addRow(self.lbl_picture, self.edt_picture)
        self.edt_form = QLineEdit()
        self.lbl_form = QLabel("ФОРМА")
        form3.addRow(self.lbl_form, self.edt_form)
        self.trash = DocumBox(self)                                     
        self.trash.setContextMenuPolicy(Qt.CustomContextMenu)           
        self.trash.customContextMenuRequested.connect(self.sc_menu_docum)
        form3.addRow("ЛОГОИП,\nМАКЕТ", self.trash)
        self.edt_docum = QLineEdit()                                            # поле названия файла
        self.edt_docum.setReadOnly(True)                                        # название файла только для чтения
        form3.addRow(self.edt_docum)
        gbox3 = QGroupBox()
        gbox3.setLayout(form3)

        vbox2.addWidget(gbox2)
        vbox1.addWidget(gbox3)
        
        lbl_note = QLabel("КОММЕНТАРИЙ")
        vbox2.addWidget(lbl_note)                                         
        self.pte_note = QPlainTextEdit()
        vbox2.addWidget(self.pte_note)                                         
        self.chb_quickly = QCheckBox("СРОЧНО")
        vbox2.addWidget(self.chb_quickly)                                     
        btn_quit = QPushButton('ПОСТАВИТЬ В ОЧЕРЕДЬ И ЗАКРЫТЬ ФОРМУ')
        btn_quit.clicked.connect(self.set_order)
        vbox2.addWidget(btn_quit)                                              

        hbox = QHBoxLayout()
        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)

        self.setLayout(hbox)
        self.setWindowModality(1)
        self.setWindowTitle("МОДУЛЬ")
        self.resize(500,50)
        self.show()


    def load_data(self, rec_id):


        """ Изменить."""
        items = ("", "ТЕКСТ","ДИЗАЙН","ФОРМАТ")
        self.model_modification = QStringListModel(items, self)
        self.cmb_modification.setModel(self.model_modification)

        """ ГАЗЕТА."""
        items = ("", "САМАРА","ТОЛЬЯТТИ")
        self.model_city = QStringListModel(items, self)
        self.cmb_city.setModel(self.model_city)

        # model
        self.model = QSqlRelationalTableModel()
        self.model.setTable("store")
        column = field_column(self.model)
        self.model.setFilter('store.rec_id={}'.format(rec_id))
        self.model.setRelation(column['class'],
            QSqlRelation("class_code", "rec_id", "class"))
        self.model.select()

        self.cmb_class.setModel(self.model.relationModel(column['class']))
        self.cmb_class.setModelColumn(2)

        # mapper
        self.mapper = QDataWidgetMapper()
        self.mapper.setSubmitPolicy(QDataWidgetMapper.ManualSubmit)
        self.mapper.setModel(self.model)
        self.mapper.setItemDelegate(QSqlRelationalDelegate())

        self.mapper.addMapping(self.cmb_class, column['class'])
        self.mapper.addMapping(self.cmb_modification,
            column['modification'], 'currentIndex')
        self.mapper.addMapping(self.edt_num_asu_old, column['num_asu_old'])
        self.mapper.addMapping(self.cmb_city, column['city'], 'currentIndex')
        self.mapper.addMapping(self.edt_num_asu_new, column['num_asu_new'])
        self.mapper.addMapping(self.edt_place, column['place'])
        self.mapper.addMapping(self.edt_num_out, column['num_out'])
        self.mapper.addMapping(self.edt_proportions, column['proportions'])
        self.mapper.addMapping(self.edt_color, column['color'])
        self.mapper.addMapping(self.edt_picture, column['picture'])
        self.mapper.addMapping(self.edt_form, column['form'])
        self.mapper.addMapping(self.pte_note, column['note'])
        self.mapper.addMapping(self.edt_docum, column['logo_name'])
        self.mapper.addMapping(self.chb_quickly, column['quickly'])
        self.mapper.toFirst()

        if self.edt_docum.text():
            self.trash.setPixmap(self.pict_full)

    def class_changed(self,index):
    
        def modification(bool):
            self.lbl_modification.setVisible(bool)
            self.cmb_modification.setVisible(bool)
            self.lbl_num_asu_old.setVisible(bool)
            self.edt_num_asu_old.setVisible(bool)
            
        def customer(bool):
            self.lbl_num_asu_new.setVisible(bool)
            self.edt_num_asu_new.setVisible(bool)
            self.lbl_place.setVisible(bool)
            self.edt_place.setVisible(bool)
            self.lbl_num_out.setVisible(bool)
            self.edt_num_out.setVisible(bool)
            
            self.lbl_color.setVisible(bool)
            self.edt_color.setVisible(bool)
            self.lbl_picture.setVisible(bool)
            self.edt_picture.setVisible(bool)
            self.lbl_form.setVisible(bool)
            self.edt_form.setVisible(bool)

        if index == "новый макет":
            modification(False)
            customer(True)
        
        if index == "изменение макета":
            modification(True)
            customer(True)

        if index == "макет заказчика":
            modification(False)
            customer(False)

    def set_order(self):

        """ПРОВЕРКА ЗАПОЛНЕНИЯ ПОЛЕЙ"""
        if self.cmb_class.currentIndex() not in (1,2,4):
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ЗАДАНИЕ нужно выбрать: <НОВЫЙ>, <ИЗМЕНЕНИЯ> или <МАКЕТ ЗАКАЗЧИКА>.")
            return
        if (self.cmb_class.currentIndex()==2):
            if self.cmb_modification.currentIndex()==0:
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле ИЗМЕНИТЬ нужно выбрать:  <ТЕКСТ>, <ДИЗАЙН> или <ФОРМАТ>.")
                return
            if self.edt_num_asu_old.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле СТАРЫЙ МАКЕТ нужно указать номер старого модуля из АСУ газеты.")
                return
        if self.cmb_city.currentIndex()==0:
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ГАЗЕТА нужно выбрать: <ТОЛЬЯТТИ> или <САМАРА>.")
            return
        if self.cmb_class.currentIndex() in (1,2):
            if self.edt_num_asu_new.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле № АСУ нужно указать номер нового модуля из АСУ газеты.")
                return
            if self.edt_place.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле РУБРИКА нужно указать рубрику нового модуля из АСУ газеты.")
                return
            if self.edt_num_out.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "В поле НОМЕР ВЫХОДА нужно указать номер газеты.")
                return
        if self.edt_proportions.text()=='':
            QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                "В поле ФОРМАТ МОДУЛЯ нужно указать формат модуля.")
            return
        if self.cmb_class.currentIndex()==4:
            if self.edt_docum.text()=='':
                QMessageBox.critical(self,"НЕДОСТАТОЧНО ИНФОРМАЦИИ",
                    "Положите макет заказчика В КОРЗИНУ ДЛЯ ДОКУМЕНТОВ.")
                return

        """ Поставить в очередь. Сохранить результаты"""
        self.model.setData(self.model.index(0,DATA_READY), 1)
        d = datetime.datetime.today()
        self.model.setData(self.model.index(0,DATE_ORDER), d.strftime('%Y-%m-%d %H:%M:%S'))
        self.mapper.submit()
        self.accept()

    def closeEvent(self,е):
        """ Закрытие формы крестиком. Результаты сохраняем, но готовность не
        ставим."""
        self.mapper.submit()
        self.accept()

    def sc_menu_docum(self, pos):

        menu = QMenu(self)
        menu.addAction("Добавить документ", self.add_file)
        menu.addAction("Очистить корзину", self.delete_file)
        menu.exec_(QCursor.pos())

    def add_file(self):
    
        """ ДОБАВИТЬ ДОКУМЕНТ в КОРЗИНУ.
        Находим путь до рабочего стола. Открываем диалог открытия файла."""
        user_profile = os.environ['USERPROFILE']
        user_desktop = user_profile + "/Desktop"
        url, filter  = QFileDialog.getOpenFileName(self,
            caption="Заголовок окна", directory=user_desktop,
            filter="All(*.*)")
        """ записываем file_name во внутреннюю переменную."""
        file_to_blob(url, self.rec_id)
        path, file = os.path.split(url)
        self.edt_docum.setText(file)
        self.trash.setPixmap(self.pict_full)

    def delete_file(self):
    
        """ Очистить корзину."""
        query = QSqlQuery()
        query.exec("UPDATE store SET logo=NULL WHERE rec_id = {};"
            .format(self.rec_id))
        self.edt_docum.setText("")
        self.trash.setPixmap(self.pict_empty)


class DocumBox(QLabel):
    """ ВИДЖЕТ - КОРЗИНА ДЛЯ ДОКУМЕНТОВ"""

    def __init__(self, dialog):
        super().__init__()

        """ Запомнить ссылку на диалог, чтобы иметь доступ ко всем виджетам
        формы. Разрешаем прием. Нужны две картинки: пустая корзин, полная
        корзина."""
        self.dialog = dialog
        self.setAcceptDrops(True)
        self.setPixmap(dialog.pict_empty)

    def dragEnterEvent(self, event):

        # drop1
        """ Если сбрасывается URL файлов, то разрешаем."""
        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):

        # drop2
        """ Можно сбросить только один файл. """
        urls = []
        for url in event.mimeData().urls():
            urls.append(url.toLocalFile())
        if len(urls) > 1:
            QMessageBox.critical(self,"НЕВОЗМОЖНО СОХРАНИТЬ",
                "Можно сохранить только один файд любого типа.")
        """ Сохраняем файл в БД. Сохраняем название файла. Меняем картинку на
        полную корзину."""
        url = urls[0]
        file_to_blob(url, self.dialog.rec_id)
        path, file = os.path.split(url)
        self.dialog.edt_docum.setText(file)
        self.setPixmap(self.dialog.pict_full)
        
    def mousePressEvent(self, pe):
    
        # drag1
        if pe.button() == Qt.LeftButton:
            self.m_ptDragPos = pe.pos()
        QWidget.mousePressEvent(self, pe) # посылаем сигнал дальше

    def mouseMoveEvent(self, pe):
    
        # drag2
        if (pe.buttons() == Qt.LeftButton):
            distance = (pe.pos() - self.m_ptDragPos).manhattanLength()
            if (distance > QApplication.startDragDistance()):
                if self.dialog.edt_docum.text():
                    self.startDrag()
        QWidget.mousePressEvent(self, pe)
        
    def startDrag(self):  

        # drag3
        name_file = ("{}\\{}".format(os.getenv('APPDATA'), 
            self.dialog.edt_docum.text()))
        query = QSqlQuery()
        query.exec("SELECT logo FROM store WHERE rec_id = {};"
            .format(self.dialog.rec_id))
        if query.lastError().isValid ():
            print('ошибка чтения блоба')
            logging.critical('Поле логин: {}'.format( query.lastError().text()))
        query.next()    
        f = open(name_file,'wb')
        f.write(query.value(0))
        f.close()
        url = QUrl.fromLocalFile(name_file);
        # print(url)
        mimeData = QMimeData()
        mimeData.setUrls([url])  
        drag = QDrag(self)
        drag.setMimeData(mimeData)
        drag.setPixmap(QPixmap('pict/dropdrag.png')) 
        drag.exec_(Qt.MoveAction)

def file_to_blob(url, rec_id):

    data = open(url, 'rb').read()
    query = QSqlQuery()
    query.prepare("UPDATE store SET logo=(:data) WHERE rec_id = {};"
        .format(rec_id))
    query.bindValue(":data", QByteArray(data))
    query.exec_()


if __name__ == '__main__':

    app = QApplication(sys.argv)
    app.setStyleSheet(
            """QGroupBox {
            border: 1px solid gray;
            border-radius: 3px;
            margin: 10px;
            padding: 4px;
            }

            QGroupBox::title {
            subcontrol-origin: margin;
            subcontrol-position: top center;
            padding: 4px;
            }"""    )

    # уходим в рабочий каталог головного модуля куда потом он будет импортирован
    os.chdir('..')

    import logging

    logging.basicConfig(filename='modulemenager.log',level=logging.DEBUG,
        format = u'%(filename)s[LINE:%(lineno)d]# %(levelname)-8s %(message)s')

    from connmysql import get_db_mysql

    """ Соединение с БД."""
    db = get_db_mysql("order.ini")
    if not db:
        print("нет соединения")
        quit()

    module = ModuleMenager(None,'1388')
    module.exec_()
    db.close()
    quit()

    sys.exit(app.exec_())
